<!DOCTYPE html>
<html>

<head>
  <script src="/js/face-api.js"></script>
  <!-- <script src="js/commons.js"></script> -->
  <script src="/js/faceDetectionControls.js"></script>
  <link rel="stylesheet" href="./styles.css">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/materialize/0.100.2/css/materialize.css">
  <script type="text/javascript" src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
  <style>
    canvas {
      position: absolute;
    }

    header,
    main,
    footer {
      padding-left: 20vw;
    }

    body {
      width: 100vw;
      left: 0vw;
      /* position: absolute; */
      display: flex;
      min-height: 100vh;
      flex-direction: column;
    }

    main {
      flex: 1 0 auto;
    }

    @media only screen and (max-width : 992px) {

      header,
      main,
      footer {
        padding-left: 0;
      }
    }
  </style>
</head>
<header>
  <!-- <div id="navbar"></div> -->
  <nav>
    <div class="nav-wrapper">
      <a href="#" data-activates="slide-out" class="button-collapse"><i class="material-icons">menu</i></a>
      <a href="" class="brand-logo" style="margin-left: 1vw;">Raimrime</a>
      <ul id="nav-mobile" class="right hide-on-med-and-down">
        <li><a href="https://rainrime.top">my blog</a></li>
      </ul>
    </div>
  </nav>

  <div id="slide-out" class="side-nav" style="width: 60vw;">
    <nav>
      <div class="nav-wrapper">
        <a href="" class="brand-logo" style="margin-left: 1vw;">案例</a>
      </div>
    </nav>
    <div class="row" style="width: 85%; margin-top: 20px;">
      <div class="card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi003.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">Age and gender recognition</p>
        </div>
      </div>
      <div class=" card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi001.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">landmarks draw</p>
        </div>
      </div>
      <div class=" card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi002.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">expression recognition</p>
        </div>
      </div>
    </div>
  </div>
  <div id="slide-out2" class="side-nav fixed" style="width: 20vw;">
    <div class="row" style="width: 85%; margin-top: 20px;">
      <div class="card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi003.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">Age and gender recognition</p>
        </div>
      </div>
      <div class=" card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi001.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">landmarks draw</p>
        </div>
      </div>
      <div class=" card">
        <div class="card-image">
          <img src="https://tuchuangrrr.oss-cn-shenzhen.aliyuncs.com/img/faceapi002.png">
        </div>
        <div class="card-content" style="background-color: #ee6e73;">
          <p style="color: cornsilk;">expression recognition</p>
        </div>
      </div>
    </div>


</header>

<body text-align:center>
  <main>
    <div class="row">
      <div class="center-content">
        <div class="col s12 m12">
          <div class="card-panel teal">
            <span class="white-text"> Realtime facedection and expression recognition, please first read the footer
              before you start video
            </span>
            <!-- <span id="whoami" class="white-text">start?</span> -->
          </div>
          <div class="progress" id="loader">
            <div class="indeterminate"></div>
          </div>
          <div class="col s6 m6">
            <div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
              <select id="selectFaceDetector">
                <!-- <option value="ssd_mobilenetv1">SSD Mobilenet V1</option> -->
                <option value="tiny_face_detector">Tiny Face Detector</option>
              </select>
              <label>Select Face Detector</label>
            </div>
          </div>
          <div class="col s6 m6">
            <span id="tiny_face_detector_controls">
              <div class="row input-field" style="margin-right: 20px;">
                <select id="inputSize">
                  <option value="" disabled selected>Input Size:</option>
                  <option value="128">128 x 128</option>
                  <option value="160">160 x 160</option>
                  <option value="224">224 x 224</option>
                  <option value="320">320 x 320</option>
                  <option value="416">416 x 416</option>
                  <option value="512">512 x 512</option>
                  <option value="608">608 x 608</option>
                </select>
                <label>Input Size</label>
              </div>
            </span>
          </div>
        </div>

        <div>
          <div id="waitingProgress" class="progress">
            <div class="indeterminate"></div>
          </div>
          <div style="position: relative" class="margin" style="margin-left: a;">
            <video class="responsive-video" onloadedmetadata="onPlay(this)" id="inputVideo" style="max-height: 60vh;"
              autoplay muted playsinline></video>
            <!-- <video class="responsive-video" id="inputVideo" style="max-height: 60vh;" autoplay muted playsinline></video> -->
            <canvas id="overlay" style="max-height: 60vh;" />
          </div>
        </div>
        <!-- <div style="height: 50vh;"><p>mesfasfasfasfd</p></div> -->
        <!-- <div class="col s9" style="justify-content:center"> -->
        <!-- Teal page content  -->
        <div class="row" style="margin-top: 50px;">
          <div class="col s12 m12">
            <div id="waitNameDiv" style="text-align: center;">
              <div class="preloader-wrapper active">
                <div class="spinner-layer spinner-red-only">
                  <div class="circle-clipper left">
                    <div class="circle"></div>
                  </div>
                  <div class="gap-patch">
                    <div class="circle"></div>
                  </div>
                  <div class="circle-clipper right">
                    <div class="circle"></div>
                  </div>
                </div>
              </div>
            </div>
            <div id="showNameDiv" style="text-align: center;">
              <p>Hello ! Maybe you are: </p>
              <div id="toShowName">
                <div id="showname" class="chip">
                  hello
                  <!-- <p id="showname">showname</p> -->
                  <!-- <i class="close material-icons">close</i> -->
                </div>
              </div>
            </div>
            <div id="fps_meter" class="row side-by-side">
              <div>
                <label for="time">Time:</label>
                <input disabled value="-" id="time" type="text" class="bold">
                <label for="fps">Estimated Fps:</label>
                <input disabled value="-" id="fps" type="text" class="bold">
              </div>
            </div>
          </div>
          <div style="text-align:center;">
            <button class="btn waves-effect waves-light red" type="submit" name="action" onclick="run()">Start
              <i class="material-icons right">send</i>
            </button>
          </div>
          <!-- Modal Trigger -->
          <!-- <a class="waves-effect waves-light btn" href="#modal1">模态</a> -->

          <!-- Modal Structure -->
          <!-- <a class="btn-floating btn-large waves-effect waves-light red"><i class="material-icons">add</i></a> -->
          <!-- <button class="waves-effect waves-light btn" onclick="RecognizeShow()" style="margin-left: auto;">
                Ok
              </button> -->
          <!-- <div>
            <p id="showname">hello</p>
            <button id="capture">拍照</button>
                </div>
            <canvas id="thecanvas" width="480" height="320"></canvas>
          </div> -->
        </div>
      </div>
    </div>
  </main>

  <footer class="page-footer">
    <div class="container">
      <div class="row">
        <div class="col l6 s12">
          <h5 class="white-text">Thank you for visit here.</h5>
          <p class="grey-text text-lighten-4">The test demo has not been completed.
          </p>
          <p class="grey-text text-lighten-4">If you have some good ideas to share,
            you could contact with me. Or you may use the Message Board of my blog.
          </p>
        </div>
        <div class="col l4 offset-l2 s12">
          <!-- <h5 class="white-text">Thanks for these projects</h5>
          <ul>
              <li><a class="grey-text text-lighten-3" href="https://www.tensorflow.org/js">tensorflow.js</a></li>
              <li><a class="grey-text text-lighten-3" href="https://justadudewhohacks.github.io/face-api.js/docs/index.html">faceapi.js</a></li>
              <li><a class="grey-text text-lighten-3" href="https://materializecss.com/">Materialize</a></li>
              <li><a class="grey-text text-lighten-3" href="https://docs.opencv.org/3.4/d5/d10/tutorial_js_root.html">opencv.js</a></li>
          </ul> -->
          <h5 class="white-text">Some extra notes !</h5>
          <p class="grey-text text-lighten-4">The demo is just a static page.
            <br>It totally runs on your browser after loading all files.
            <br>So you need not warry about the camera will reveal your privacy.</p>
        </div>
      </div>
    </div>
    <div class="footer-copyright">
      <div class="container">
        © 2020 Copyright Rainrime
        <a class="grey-text text-lighten-4 right" href="http://rainrime.top">For more
          details,
          please visit my
          blog</a>
      </div>
    </div>
  </footer>
  <script>
    $(" .button-collapse").sideNav()
    $('.modal').modal();
    themodal=document.getElementById('modal1')
    // themodal.modal('open')
    let forwardTimes = []
    let withBoxes = true
    var labeledLoaded = 0
    var faceMatcher = null
    const abcVideo = $('#inputVideo').get(0)
    var oldlength = 0
    var startVideo = 0
    // var thecanvas = document.getElementById('thecanvas');
    // var context = thecanvas.getContext('2d');
    // capture.addEventListener('click',function() {
    // 将video画面描绘在canvas画布上
    // context.drawImage(abcVideo,0,0,480,320);
    // })

    function onChangeHideBoundingBoxes(e) {
      withBoxes = !$(e.target).prop('checked')
    }
    function updateTimeStats(timeInMs) {
      forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30)
      const avgTimeInMs = forwardTimes.reduce((total, t) => total + t) / forwardTimes.length
      $('#time').val(`${Math.round(avgTimeInMs)} ms`)
      $('#fps').val(`${faceapi.utils.round(1000 / avgTimeInMs)}`)
    }
    // abcVideo.addEventListener('play', () => {
    //   // const canvas = faceapi.createCanvasFromMedia(abcVideo)
    //   // document.body.append(canvas)
    //   // abcVideo.after(canvas)
    //   const canvas = $('#overlay').get(0)
    //   // const dims = faceapi.matchDimensions(canvas, videoEl, true)
    //   // console.log(dims)
    //   // const resizedResult = faceapi.resizeResults(results, dims)

    //   // const displaySize = { width: abcVideo.width, height: abcVideo.height }
    //   const displaySize = faceapi.matchDimensions(canvas, abcVideo, true)
    //   faceapi.matchDimensions(canvas, displaySize)
    //   setInterval(async () => {
    //     const ts = Date.now()
    //     const options = getFaceDetectorOptions()
    //     const detections = await faceapi.detectAllFaces(abcVideo, options).withFaceExpressions()
    //     const resizedDetections = faceapi.resizeResults(detections, displaySize)
    //     updateTimeStats(Date.now() - ts)
    //     canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
    //     faceapi.draw.drawDetections(canvas, resizedDetections)
    //     // faceapi.draw.drawFaceLandmarks(canvas, resizedDetections)
    //     faceapi.draw.drawFaceExpressions(canvas, resizedDetections)
    //     // results = resizedDetections.map(d => faceMatcher.findBestMatch(d.descriptor))
    //     // results.forEach((result, i) => {
    //     // const box = resizedDetections[i].detection.box
    //     // const drawBox = new faceapi.draw.DrawBox(box, { label: result.toString() })
    //     // drawBox.draw(canvas)
    //     // })
    //   }, 100)
    // })
    async function onPlay() {
      const videoEl = $('#inputVideo').get(0)
      if (videoEl.paused || videoEl.ended || !isFaceDetectionModelLoaded())
        return setTimeout(() => onPlay())
      const options = getFaceDetectorOptions()
      const ts = Date.now()
      const results = await faceapi.detectAllFaces(videoEl, options).withFaceExpressions()
      result = results[0];
      oldlength = results.length
      updateTimeStats(Date.now() - ts)
      if (result) {
        autoShowFace()
        if (results.length != oldlength) {
          RecognizeShow()
          console.log(results.length)
        }
        const canvas = $('#overlay').get(0)
        const dims = faceapi.matchDimensions(canvas, videoEl, true)
        // console.log(dims)
        const resizedResult = faceapi.resizeResults(results, dims)
        const minConfidence = 0.05
        if (withBoxes) {
          faceapi.draw.drawDetections(canvas, resizedResult)
        }
        faceapi.draw.drawFaceExpressions(canvas, resizedResult, minConfidence)
      }
      setTimeout(() => onPlay())
    }
    function autoShowFace() {
      // console.log(labeledLoaded)
      if (labeledLoaded % 120 == 30) {
        RecognizeShow()
        // $('#waitingProgress').hide()
        $('#waitNameDiv').hide()
        $('#showNameDiv').show()
      }
      labeledLoaded++
      // console.log(labeledLoaded)
    }
    async function RecognizeShow() {
      if (labeledLoaded == 0) {
        const labeledFaceDescriptors = await loadLabeledImages()
        faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.6)
        console.log("loaded success")
        labeledLoaded = 1
        // console.log("init"+labeledLoaded)
      }

      if (!faceMatcher || !startVideo) {
        return
      }
      // console.log("RecognizeShow")
      const inputImgEl = $('#inputVideo').get(0)
      // const inputImgEl = $('#queryImg').get(0)
      // const canvas = $('#queryImgOverlay').get(0)

      const results = await faceapi
        .detectAllFaces(inputImgEl, getFaceDetectorOptions())
        .withFaceLandmarks()
        .withFaceDescriptors()
      // const dims = faceapi.matchDimensions(canvas, inputImgEl, true)
      // const resizedResults = faceapi.resizeResults(results, dims)
      theLabels = []
      $('#toShowName').get(0).innerHTML = ''
      results.forEach(({ detection, descriptor }) => {
        const label = faceMatcher.findBestMatch(descriptor).toString()
        console.log(label)
        // theLabels.push('&nbsp' + faceMatcher.findBestMatch(descriptor).toString().slice(0, -6) + '&nbsp')
        let newDiv = document.createElement('div')
        newDiv.setAttribute("class", "chip");
        // newDiv.class = "chip"
        newDiv.innerHTML = '&nbsp' + label.slice(0, -6) + '&nbsp'
        $('#toShowName').get(0).appendChild(newDiv)
        // const options = { label }
        // const drawBox = new faceapi.draw.DrawBox(detection.box, options)
        // drawBox.draw(canvas)
      })
      // $('#showname').get(0).innerHTML = theLabels;

    }

    async function run() {
      // load face detection and face expression recognition models
      // await changeFaceDetector(TINY_FACE_DETECTOR)
      // await faceapi.loadFaceExpressionModel('/models')
      // changeInputSize(224)

      // await faceapi.loadFaceRecognitionModel('/models')
      // await faceapi.loadSsdMobilenetv1Model('/models')
      // await faceapi.loadFaceLandmarkModel('/models')
      //   await faceapi.nets.TinyfaceLandmark68Net.loadFromUri('/models')
      // await faceapi.loadFaceLandmarkTinyModel('/models')
      // try to access users webcam and stream the images
      // to the video element
      const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
      const videoEl = $('#inputVideo').get(0)
      videoEl.srcObject = stream
      startVideo = 1
      $('#waitingProgress').show()
      $('#waitNameDiv').show()
    }
    async function runBefore() {
      // load face detection and face expression recognition models
      await changeFaceDetector(TINY_FACE_DETECTOR)
      await faceapi.loadFaceExpressionModel('/models')
      changeInputSize(224)

      await faceapi.loadFaceRecognitionModel('/models')
      // await faceapi.loadSsdMobilenetv1Model('/models')
      await faceapi.loadFaceLandmarkModel('/models')
      //   await faceapi.nets.TinyfaceLandmark68Net.loadFromUri('/models')
      // await faceapi.loadFaceLandmarkTinyModel('/models')
      // try to access users webcam and stream the images
      // to the video element
    }
    function updateResults() { }
    $(document).ready(function () {
      
      // $('#modal1').modal('open');
      $('#waitingProgress').hide()
      $('#waitNameDiv').hide()
      $('#showNameDiv').hide()
      // renderNavBar('#navbar', 'webcam_face_expression_recognition')
      initFaceDetectionControls()
      RecognizeShow()
      runBefore()
      // run()
    })
    function loadLabeledImages() {
      // const labels = ['kun','smallxianxian']
      const labels = ['kun', 'smallxianxian', 'hxy']
      return Promise.all(
        labels.map(async label => {
          // I changed
          var obj = await faceapi.fetchJson("/models/label_im/" + label + ".json")
          console.log(obj)
          console.log("objcheck")

          const ret = []
          for (let i = 0; i < obj.length; i++) {
            let valArr = Object.keys(obj[0]).map(function (x) { return obj[0][x] })
            ret.push(Float32Array.from(valArr));
          }
          console.log(ret)
          return new faceapi.LabeledFaceDescriptors(label, ret)
        })
      )
    }
  </script>

</html>